package com.yifeng.repo.controller.excel.loader.worker;

import com.alibaba.excel.support.ExcelTypeEnum;
import com.gomcarter.frameworks.base.common.AssertUtils;
import com.gomcarter.frameworks.base.exception.CustomException;
import com.gomcarter.frameworks.base.json.JsonObject;
import com.talkyun.utils.revised.http.HttpConnector;
import com.talkyun.utils.revised.http.HttpResult;
import com.yifeng.lsd.client.LsdClientHelper;
import com.yifeng.lsd.util.Base64Utils;
import com.yifeng.lsd.util.CommonUtils;
import com.yifeng.lsd.vo.TokenInfo;
import com.yifeng.lsd.vo.status.RequestType;
import com.yifeng.repo.base.constant.BaseConstant;
import com.yifeng.repo.base.params.ConsoleParam;
import com.yifeng.repo.base.security.proxy.CommonProxy;
import com.yifeng.repo.base.utils.converter.JacksonHelper;
import com.yifeng.repo.base.utils.file.FileHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Collections;

@Slf4j
public class LsdWorker extends CommonProxy {

    private final String mapping;

    public LsdWorker(ConsoleParam consoleParam) {
        super(consoleParam);
        this.mapping = "/yflsd/lsdHelper";
    }

    public void callLsd(File sourceFile, File targetFile, ExcelTypeEnum excelType, String reason) {
        String url = consoleParam.getUrl() + mapping + "/callLsd";
        try {
            // 读取本地文件
            byte[] bytes = FileUtils.readFileToByteArray(sourceFile);

            // 如果本地文件没有加密，就直接返回
            if (!CommonUtils.isEncrypt(bytes)) {
                FileHelper.copyFile(sourceFile, targetFile);
                return;
            }

            // 通过Lsd工具来解密
            TokenInfo tokenInfo = new TokenInfo();
            tokenInfo.setSuffix(excelType.getValue());
            tokenInfo.setReason(reason);
            tokenInfo.setUserId(consoleParam.getAppId());
            tokenInfo.setHandleType(RequestType.decipher.name());
            String fileBase64 = new String(Base64Utils.encode(bytes), StandardCharsets.UTF_8);
            String cryptBase64Content = LsdClientHelper.buildDecryptInfoByPrivateKey(consoleParam.getAppId(), consoleParam.getAccessToken(), fileBase64, tokenInfo);
            String decryptBase64Content = doActionCall(url, cryptBase64Content);
            FileUtils.writeByteArrayToFile(targetFile, Base64Utils.decode(decryptBase64Content));
        } catch (Exception e) {
            throw new CustomException(sourceFile.getAbsolutePath() + " callLsd failed, error=", e);
        }
    }

    private String doActionCall(String url, String body) {
        HttpResult result = doInvoke(BaseConstant.HTTP_POST_METHOD, url, body);
        AssertUtils.isTrue(result.success(), String.format("Post failed，url：%s, status: %s, error: %s", url, result.getStatus(), result.getResult()));
        JsonObject jsonObject = JacksonHelper.toObj(result.getResult(), JsonObject.class);
        AssertUtils.isTrue(jsonObject.getCode() == 0, new CustomException(jsonObject.getCode(), jsonObject.getMessage()));
        AssertUtils.notNull(jsonObject.getData(), "正确返回，但是返回数据错误：" + result.getResult());
        return jsonObject.getData().toString();
    }

    @Override
    protected HttpResult doInvoke(String method, String url, String body) {
        for (int i = 0; i < consoleParam.getTryTimes(); i++) {
            try {
                HttpConnector conn = CONNECTOR_FACTORY.getConnector(url, consoleParam.getClientTimeoutMillis());
                return conn.sendWithHeader(method, Collections.emptyMap(), body);
            } catch (Throwable t) {
                if (consoleParam.getTryTimes() - 1 > i) {
                    // doSleep(1000);
                    continue;
                }
                throw new CustomException(String.format("invoke failed: url=%s, body=%s, error=%s", url, body, t.getClass().getName()));
            }
        }
        throw new CustomException("invoke failed: url=" + url + ", body=" + body);
    }
}
